<!--
vant-ui 扩展表单的完整的代码
-->
<template>
  <div>
    <slot name="items"></slot>
  </div>
</template>
<script>
// import { testFunc } from './init.js'
/**
 * author：ronggang
 * email：suntework@163.com
 */
export default {
  name: 'VantForm',
  props: {
    inputVail: {
      type: Boolean,
      default: false
    },
    rules: {
      type: Object,
      default() {
        return {}
      }
    }
  },
  data () {
    return {
      rulesEles: []
    }
  },
  mounted () {
    // 递归获取所有带有 rule 属性的元素
    this.rulesEles = this.getRuleEle(this, this.$slots.items)
    // 处理 输入监听的校验
    if (this.inputVail) {
      this.$nextTick(() => {
        this.eleSetInput(this)
      })
    }
  },
  methods: {
    // 递归获取插槽内所有拥有 input 属性的元素【内部方法】
    getRuleEle (self, eleObj) {
      let childs = []
      // debugger
      if (!eleObj) return
      // 循环所有元素（兼容 对象和数组的情况）
      const arr = eleObj instanceof Array ? eleObj : [eleObj]
      for (const i in arr) {
        const ele = eleObj[i]
        // 当前元素包含 rule 属性，则收录起来 rules
        if (ele.data && self.rules) {
          const elements = ele.elm
          const inputArr = Array.prototype.slice.call(elements.querySelectorAll('input'))
          const textareaArr = Array.prototype.slice.call(elements.querySelectorAll('textarea'))
          childs = childs.concat(inputArr, textareaArr)
          childs.map(dom => {
            this.setErrMsgDom(dom, 'none')
          })
        }
        // 当前元素存在子元素，则递归查询
        ele.children && childs.push.apply(childs, this.getRuleEle(self, ele.children))
      }
      return childs
    },
    // 设置校验提示信息的隐藏和显示
    setErrMsgDom (dom, display) {
      const pDom = dom.parentNode
      const pDom1 = pDom.parentNode
      const errDom = pDom1.querySelector('.van-field__error-message')
      if (errDom) {
        errDom.style.display = display
      }
    },
    // 设置 需要校验的属性 的 input监听 校验 【内部方法】
    eleSetInput (self) {
      try {
        for (const i in self.rulesEles) {
          (function (index) {
          // 绑定 input 事件
            const inputEle = self.rulesEles[index]
            // console.log('inputEle', inputEle)
            inputEle.oninput = function () {
            // 输入实时校验
              self.handleVail(self, index)
            }
          })(i)
        }
      } catch (e) {
        console.error('vail error：' + e)
      }
    },
    // 检验元素的值是否满足条件（参数：索引值 ）【内部方法】
    handleVail (self, i) {
      try {
      // 获取元素下 input 元素（目前只针对 单个输入框做处理）
        const inputEle = self.rulesEles[i]
        const inputValue = inputEle.value
        const dataSetRule = inputEle.dataset.rule
        // console.log('dataSetRule', dataSetRule)
        // if (dataSetRule === 'C004005') {
        //   debugger
        // }
        let vailFlag = true
        // 获取设置的校验规则
        const ruleObj = self.rules ? self.rules[dataSetRule] : null
        if (!ruleObj) return vailFlag
        // 非空校验
        vailFlag = ruleObj.required ? !!inputValue : vailFlag
        // 正则校验
        vailFlag = ruleObj.regExp ? ruleObj.regExp.test(inputValue) && vailFlag : vailFlag
        // 用户自定义校验
        vailFlag = typeof ruleObj.handleVailFun === 'function' ? ruleObj.handleVailFun(inputValue) && vailFlag : vailFlag
        // 获取组件实例，修改错误信息(注释的代码可以实现效果，但是违反了子组件修改父组件的规则)
        // 目前是通过控制元素显示隐藏去实现错误信息的展示
        if (!vailFlag) {
          this.setErrMsgDom(inputEle, 'block')
        } else {
          this.setErrMsgDom(inputEle, 'none')
        }
        return vailFlag
      } catch (e) {
        console.error('vail error：' + e)
      }
    },
    // 整体校验【对外提供方法】
    allVail () {
      const self = this
      let flag = true
      for (const i in this.rulesEles) {
        flag = !self.handleVail(self, i) ? false : flag && true
      }

      if (!flag) {
        this.$notice.tip(4, '请按表单要求填写')
      }

      return flag
    }
  }
}
</script>
<style>
</style>
